
#ifndef RAYTRACING_PARAMETER_H
#define RAYTRACING_PARAMETER_H

/**
 * 仍然是UI界面部分，是光追仿真参数的设置，用于RayTracingWindow中的参数设置
 * 通过qml与C++中的数据绑定来实现
 *
 * !!!!!!!!
 * !!!!!!TODO::qml界面还没有进行更改----先放着，用初始值跑个demo先
 *
 */

#include <QObject>
#include <QString>

#include <algorithm/shared/utils/Vec2.h>
#include <algorithm/shared/utils/Vec3.h>

namespace solar
{
    class RayTracingParameter : public QObject
    {
            Q_OBJECT

            Q_PROPERTY(float pixel_length READ getPixelLength WRITE setPixelLength NOTIFY
                           pixelLengthChanged)
            Q_PROPERTY(float microheliostat_length READ getMicroheliostatLength WRITE
                           setMicroheliostatLength NOTIFY microheliostatLengthChanged)

            Q_PROPERTY(int num_sunshape_groups READ getNumSunshapeGroups WRITE setNumSunshapeGroups
                           NOTIFY numSunshapeGroupsChanged)
            Q_PROPERTY(int num_sunshape_lights_per_group READ getNumSunshapeLightsPerGroup WRITE
                           setNumSunshapeLightsPerGroup NOTIFY numSunshapeLightsPerGroupChanged)
            Q_PROPERTY(
                int inverse_transform_sampling_groups READ getInverseTransformSamplingGroups WRITE
                    setInverseTransformSamplingGroups NOTIFY inverseTransformSamplingGroupsChanged)

            Q_PROPERTY(float ground_length READ getGroundLength WRITE setGroundLength NOTIFY
                           groundLengthChanged)
            Q_PROPERTY(float ground_width READ getGroundWidth WRITE setGroundWidth NOTIFY
                           groundWidthChanged)

            Q_PROPERTY(
                float grid_size_x READ getGridSizeX WRITE setGridSizeX NOTIFY gridSizeXChanged)
            Q_PROPERTY(
                float grid_size_y READ getGridSizeY WRITE setGridSizeY NOTIFY gridSizeYChanged)
            Q_PROPERTY(
                float grid_size_z READ getGridSizeZ WRITE setGridSizeZ NOTIFY gridSizeZChanged)

            Q_PROPERTY(float grid_pos_x READ getGridPosX WRITE setGridPosX NOTIFY gridPosXChanged)
            Q_PROPERTY(float grid_pos_y READ getGridPosY WRITE setGridPosY NOTIFY gridPosYChanged)
            Q_PROPERTY(float grid_pos_z READ getGridPosZ WRITE setGridPosZ NOTIFY gridPosZChanged)

            Q_PROPERTY(float grid_interval_x READ getGridIntervalX WRITE setGridIntervalX NOTIFY
                           gridIntervalXChanged)
            Q_PROPERTY(float grid_interval_y READ getGridIntervalY WRITE setGridIntervalY NOTIFY
                           gridIntervalYChanged)
            Q_PROPERTY(float grid_interval_z READ getGridIntervalZ WRITE setGridIntervalZ NOTIFY
                           gridIntervalZChanged)

        public:
            RayTracingParameter() = default;

            /**
             *  用于与UI交互
             */
            [[nodiscard]] auto getPixelLength() const -> float;
            [[nodiscard]] auto getMicroheliostatLength() const -> float;

            [[nodiscard]] auto getNumSunshapeGroups() const -> int;
            [[nodiscard]] auto getNumSunshapeLightsPerGroup() const -> int;
            [[nodiscard]] auto getInverseTransformSamplingGroups() const -> int;

            [[nodiscard]] auto getGroundLength() const -> float;
            [[nodiscard]] auto getGroundWidth() const -> float;

            [[nodiscard]] auto getGridSizeX() const -> float;
            [[nodiscard]] auto getGridSizeY() const -> float;
            [[nodiscard]] auto getGridSizeZ() const -> float;

            [[nodiscard]] auto getGridPosX() const -> float;
            [[nodiscard]] auto getGridPosY() const -> float;
            [[nodiscard]] auto getGridPosZ() const -> float;

            [[nodiscard]] auto getGridIntervalX() const -> float;
            [[nodiscard]] auto getGridIntervalY() const -> float;
            [[nodiscard]] auto getGridIntervalZ() const -> float;

            // void setRayCnt(const QString& str);   // 用从ui传来的QString更新ray_cnt_
            void setPixelLength(float pixel_length);
            void setMicroheliostatLength(float microheliostat_length);

            void setNumSunshapeGroups(int num_sunshape_groups);
            void setNumSunshapeLightsPerGroup(int num_sunshape_lights_per_group);
            void setInverseTransformSamplingGroups(int inverse_transform_sampling_groups);

            void setGroundLength(float ground_length);
            void setGroundWidth(float ground_width);

            void setGridSizeX(float grid_size_x);
            void setGridSizeY(float grid_size_y);
            void setGridSizeZ(float grid_size_z);

            void setGridPosX(float grid_pos_x);
            void setGridPosY(float grid_pos_y);
            void setGridPosZ(float grid_pos_z);

            void setGridIntervalX(float grid_interval_x);
            void setGridIntervalY(float grid_interval_y);
            void setGridIntervalZ(float grid_interval_z);

            // 用于算法层调用
            [[nodiscard]] auto getGridSize() const -> Vec3 { return grid_size_; }
            [[nodiscard]] auto getGridPos() const -> Vec3 { return grid_pos_; }
            [[nodiscard]] auto getGridInterval() const -> Vec3 { return grid_interval_; }

        signals:
            // 信号，不需要实现，在qml里绑定即可
            // NOLINTBEGIN(modernize-use-trailing-return-type)
            QString pixelLengthChanged();
            QString microheliostatLengthChanged();

            QString numSunshapeGroupsChanged();
            QString numSunshapeLightsPerGroupChanged();
            QString inverseTransformSamplingGroupsChanged();

            QString groundLengthChanged();
            QString groundWidthChanged();

            QString gridSizeXChanged();
            QString gridSizeYChanged();
            QString gridSizeZChanged();

            QString gridPosXChanged();
            QString gridPosYChanged();
            QString gridPosZChanged();

            QString gridIntervalXChanged();
            QString gridIntervalYChanged();
            QString gridIntervalZChanged();
            // NOLINTEND(modernize-use-trailing-return-type)

        public slots:
            Q_INVOKABLE void
            setParameterViaFile(QString file_path); // 通过json文件设置这里所有变量的值

        private:
            double pixel_length_{0.01};          // 接收器像素尺寸
            double microheliostat_length_{0.01}; // 微定日镜尺寸

            // ray_cant  = 微定日镜个数 * 每个光锥内光线个数
            int num_sunshape_groups_{4096}; // 每个微定日镜上的光锥数目---用于random，其实每个定日镜上只有一个光锥
            int num_sunshape_lights_per_group_{32};     // 每个光锥内光线的数目
            int inverse_transform_sampling_groups_{128}; // 用于插值逆变换采样

            double ground_length_{1800}; // 整个场景的范围---貌似在算法中没什么用
            double ground_width_{1800};

            Vec3 grid_size_{1600, 0.1, 1500};     // 整个grid所占的位置的大小
            Vec3 grid_pos_{-800, 0, -900};      // 位置
            Vec3 grid_interval_{40, 0.1, 30}; // 间隔
    };
} // namespace solar

#endif
